#include "dataline.h"
#include <limits>

namespace STLData{

        template<>
        Date & Date::operator=(const time_t valueEpoch) {
            epoch = valueEpoch;
            date = *(localtime(&epoch));
            return *this;
        }
        template<>
        Date & Date::operator=(const struct tm * valueDate) {
            date = *valueDate;
            epoch = mktime(&date);
            return *this;
        }
        template<>
        Date & Date::operator=(const struct tm  valueDate) {
            date = valueDate;
            epoch = mktime(&date);
            return *this;
        }
        template<>
        Date & Date::operator=(const Date valueDate) {
            date = valueDate.date;
            epoch = valueDate.epoch;
            return *this;
        }



    bool dataLineElement::operator==(const dataLineElement &other) const {
        switch (fieldData.fieldType) {
            case 'T':
                if (other.fieldData.fieldType != 'T') {
                    return false;
                } else {
                    return (fieldData.valueText == other.fieldData.valueText);
                }
                break;
            case 'R':
                return (fieldData.valueReal == other.fieldData.valueReal);
                break;
            case 'I':
                if (other.fieldData.fieldType=='R') {
                    return (fieldData.valueReal == other.fieldData.valueReal);
                } else {
                    return (fieldData.valueInt == other.fieldData.valueInt);
                }
                break;
            default:
                return false;
                break;
        }
    }

    bool dataLineElement::operator!=(const dataLineElement &other) const {
        return !(*this == other);
    }

    bool dataLineElement::operator<(const dataLineElement &other) const {
        switch (fieldData.fieldType) {
            case 'T':
                if (other.fieldData.fieldType != 'T') {
                    return false;
                } else {
                    return (fieldData.valueText < other.fieldData.valueText);
                }
                break;
            case 'R':
                return (fieldData.valueReal < other.fieldData.valueReal);
                break;
            case 'I':
                if (other.fieldData.fieldType=='R') {
                    return (fieldData.valueReal < other.fieldData.valueReal);
                } else {
                    return (fieldData.valueInt < other.fieldData.valueInt);
                }
                break;
            default:
                return false;
                break;
        }
    }

    bool dataLineElement::operator>=(const dataLineElement &other) const {
        return !(*this < other);
    }

    bool dataLineElement::operator>(const dataLineElement &other) const {
        switch (fieldData.fieldType) {
            case 'T':
                if (other.fieldData.fieldType != 'T') {
                    return false;
                } else {
                    return (fieldData.valueText > other.fieldData.valueText);
                }
                break;
            case 'R':
                return (fieldData.valueReal > other.fieldData.valueReal);
                break;
            case 'I':
                if (other.fieldData.fieldType=='R') {
                    return (fieldData.valueReal > other.fieldData.valueReal);
                } else {
                    return (fieldData.valueInt > other.fieldData.valueInt);
                }
                break;
            default:
                return false;
                break;
        }
    }

    bool dataLineElement::operator<=(const dataLineElement &other) const {
        return !(*this > other);
    }

    bool dataLine::insert(keyType searchKey, long value) {
        if (hashKey.find(searchKey)!=hashKey.end()) {
            return false;
        } else {
            hashKey[searchKey] = maxIndex;
            lineValues[maxIndex].fieldData.fieldKey = searchKey;
            lineValues[maxIndex].fieldData.fieldType = 'I';
            lineValues[maxIndex] = value;
            ++maxIndex;
            return true;
        }
    };
    bool dataLine::insert(keyType searchKey, double value) {
        if (hashKey.find(searchKey)!=hashKey.end()) {
            return false;
        } else {
            hashKey[searchKey] = maxIndex;
            lineValues[maxIndex].fieldData.fieldKey = searchKey;
            lineValues[maxIndex].fieldData.fieldType = 'R';
            lineValues[maxIndex]=value;
            ++maxIndex;
            return true;
        }
    };
    bool dataLine::insert(keyType searchKey, std::string value) {
        if (hashKey.find(searchKey)!=hashKey.end()) {
            return false;
        } else {
            hashKey[searchKey] = maxIndex;
            lineValues[maxIndex].fieldData.fieldKey = searchKey;
            lineValues[maxIndex].fieldData.fieldType = 'T';
            lineValues[maxIndex] = value;
            ++maxIndex;
            return true;
        }
    };
    bool dataLine::createField(keyType searchKey, char fieldType, int length) {
        if (hashKey.find(searchKey)!=hashKey.end()) {
            return false;
        } else {
            hashKey[searchKey] = maxIndex;
            lineValues[maxIndex].fieldData.fieldType = fieldType;
            lineValues[maxIndex].fieldData.fieldKey = searchKey;
            if (fieldType == 'T')
                lineValues[maxIndex].fieldData.stringLength = length;
            else
                lineValues[maxIndex].fieldData.stringLength = 0;
            lineValues[maxIndex].fieldData.valueText = "NaN";
            lineValues[maxIndex].fieldData.valueReal = std::numeric_limits<double>::quiet_NaN();
            lineValues[maxIndex].fieldData.valueInt = std::numeric_limits<long>::min();
            ++maxIndex;
            return true;
        }
    };

    dataLine& dataLine::operator=(const dataLine &rhs){
        dataLine::iterator left;
        dataLine::const_iterator right;
        int j = rhs.lineValues.size();
        for (int i = 0; i< maxIndex ; i++) {
            if (i < j) {
                lineValues[i] = rhs.lineValues[i];
            } else {
                break;
            }
        }
        return *this;
    }

    dataLine& dataLine::corresponding(const dataLine &rhs){

        dataLine::const_iterator right;
        for (right = rhs.begin(); right != rhs.end(); right++) {
            if (find((*right).key())!=this->end())
                operator[]((*right).key()) = *right;
        }
        return *this;

    }
}
